// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial

global Palette  {
    out property <color> window-background: #eee;
    out property <color> widget-background: #ddd;
    out property <color> widget-stroke: #888;
    out property <color> window-border: #ccc;
    out property <color> text-color: #666;
    out property <color> hyper-blue: #90d1ff;

}

//------ MdiWindow ----

component MdiWindow inherits Rectangle {
    in property <string> title;
    in-out property <length> window-x <=> window.x;
    in-out property <length> window-y <=> window.y;
    in-out property <bool> is-open: true;
    width: 100%;
    height: 100%;


    window := Rectangle {
        x:0;y:0;
        background: Palette.window-background;
        border-width: 2px;
        border-color: Palette.window-border;
        border-radius: 6px;
        drop-shadow-blur: 25px;
        drop-shadow-color: Palette.window-border;
        property <length> open-width: l.preferred-width;
        property <length> open-height: l.preferred-height;
        width: l.preferred-width;
        height: l.preferred-height - hidden.preferred-height;

        states [
            open when root.is-open : {
                width: self.open-width;
                height: self.open-height;
                expand.angle: 0deg;
                in { animate width, height, expand.angle { duration: 150ms; easing: ease; } }
                out { animate width, height, expand.angle { duration: 150ms; easing: ease; } }
            }
        ]

        clip: true;

        TouchArea {}

        l := VerticalLayout {
            padding: window.border-width;
            alignment: root.is-open ? stretch : start;
            title_bar := TouchArea {
                moved => {
                    if (self.pressed) {
                        root.window-x += self.mouse-x - self.pressed-x;
                        root.window-y += self.mouse-y - self.pressed-y;
                    }
                }

                HorizontalLayout {
                    padding: window.border-width;
                    spacing: window.border-width * 2;
                    expand := TouchArea {
                        width: 30px;
                        property <angle> angle: -90deg;
                        clicked => { root.is-open = !root.is-open; }
                        Path {
                            MoveTo { x: cos(expand.angle) * -1 - sin(expand.angle) * -1; y: sin(expand.angle) * -1 + cos(expand.angle) * -1; }
                            LineTo { x: cos(expand.angle) * 1 - sin(expand.angle) * -1; y: sin(expand.angle) * 1 + cos(expand.angle) * -1; }
                            LineTo { x: cos(expand.angle) * 0 - sin(expand.angle) * 1; y: sin(expand.angle) * 0 + cos(expand.angle) * 1; }
                            LineTo { x: cos(expand.angle) * -1 - sin(expand.angle) * -1; y: sin(expand.angle) * -1 + cos(expand.angle) * -1; }
                            stroke-width: window.border-width * (expand.has-hover ? 1.5 : 1);
                            stroke: parent.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
                            viewbox-x: -1.5;
                            viewbox-y: -1.5;
                            viewbox-height: 3;
                            viewbox-width: 3;
                        }
                    }
                    Text {
                        text: root.title;
                        horizontal-alignment: center;
                        color: Palette.text-color;
                    }
                    close_button := TouchArea {
                        width: 30px;
                        clicked => { root.visible = false; }
                        Path {
                            MoveTo { x: -1; y: -1; }
                            LineTo { x: 1; y: 1; }
                            MoveTo { x: -1; y: 1; }
                            LineTo { x: 1; y: -1; }
                            stroke-width: window.border-width * (close-button.has-hover ? 1.5 : 1);
                            stroke: parent.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
                            viewbox-x: -1.5;
                            viewbox-y: -1.5;
                            viewbox-height: 3;
                            viewbox-width: 3;
                        }
                    }
                }
            }
            hidden := VerticalLayout {
                visible: root.is-open;
                Rectangle {
                    height: window.border-width;
                    background: window.border-color;
                }
                @children
            }
        }

        if root.is-open : resize-handle := TouchArea {
            width: 20px;
            height: self.width;
            x: parent.width - self.width;
            y: parent.height - self.height;
            mouse-cursor: MouseCursor.nwse-resize;
            Path {
                MoveTo { x: 0; y: 1; }
                LineTo { x: 1; y: 0; }
                MoveTo { x: 0.4; y: 1; }
                LineTo { x: 1; y: 0.4; }
                MoveTo { x: 0.8; y: 1; }
                LineTo { x: 1; y: 0.8; }
                stroke-width: window.border-width;
                stroke: Palette.window-border;
                viewbox-height: 1.2; viewbox-width: 1.2;
            }
            moved => {
                if (self.pressed) {
                    window.open-width = max(l.min-width, min(l.max-width, window.open-width + self.mouse-x - self.pressed-x));
                    window.open-height = max(l.min-height, min(l.max-height, window.open-height + self.mouse-y - self.pressed-y));
                }
            }
        }
    }
}

//------ Widgets ------

import {LineEdit, TextEdit, ComboBox, GridBox, VerticalBox, HorizontalBox, StyleMetrics} from "std-widgets.slint";

component Label inherits Text {
    color: Palette.text-color;
}

component Button inherits TouchArea {
    min-height: t.min-height;
    min-width: t.min-width + 10px;
    in property text <=> t.text;
    Rectangle {
        border-width: 1.5px;
        border-color: root.has-hover ? Palette.widget-stroke : transparent;
        border-radius: 3px;
        background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
        t := Label {
            y:0;
            width: 100%;
            horizontal-alignment: center;
        }
    }
}

component CheckBox inherits TouchArea {
    in-out property <bool> checked;
    in property text <=> t.text;
    clicked => { root.checked = !root.checked; }
    HorizontalLayout {
        spacing: 5px;
        VerticalLayout {
            alignment: center;
            Rectangle {
                width: 20px;
                height: 20px;
                border-width: 1.5px;
                border-color: root.has-hover ? Palette.widget-stroke : transparent;
                border-radius: 3px;
                background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
                if root.checked : Path {
                    stroke: root.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
                    stroke-width: root.pressed ? 2.5px : 2px;
                    viewbox-height: 1; viewbox-width: 1;
                    MoveTo { x: 0.2; y: 0.5; }
                    LineTo { x: 0.5; y: 0.8; }
                    LineTo { x: 0.8; y: 0.2; }
                }
            }
        }
        t := Label {

        }
    }
}

component RadioButton inherits TouchArea {
    in-out property <bool> checked;
    in property text <=> t.text;
    HorizontalLayout {
        spacing: 5px;
        VerticalLayout {
            alignment: center;
            Rectangle {
                width: 20px;
                height: 20px;
                border-width: 1.5px;
                border-color: root.has-hover ? Palette.widget-stroke : transparent;
                border-radius: self.width / 2;
                background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
                if root.checked : Rectangle {
                    background: root.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
                    border-radius: self.width / 2;
                    width: parent.width / 2;
                    height: parent.width / 2;
                    x: parent.width / 4;
                    y: parent.width / 4;
                }
            }
        }
        t := Label {

        }
    }
}

component SelectableLabel inherits TouchArea {
    min-height: t.min-height;
    min-width: t.min-width + 10px;
    in-out property <bool> checked;
    in-out property text <=> t.text;
    Rectangle {
        border-width: 1.5px;
        border-color: root.has-hover ? Palette.widget-stroke : transparent;
        border-radius: 3px;
        background:
            root.checked ? Palette.hyper-blue :
            root.pressed ? Palette.widget-background.darker(30%) :
            root.has-hover ? Palette.widget-background : transparent;
        t := Label {
            y:0;
            width: 100%;
            horizontal-alignment: center;
        }
    }
}

component Slider inherits Rectangle {
    in property<float> maximum: 100;
    in property<float> minimum: 0;
    in-out property<float> value;
    in property<bool> enabled <=> touch.enabled;
    callback changed(float);

    min-height: 24px;
    min-width: 100px;
    horizontal-stretch: 1;
    vertical-stretch: 0;

    Rectangle {
        width: parent.width;
        height: parent.height / 2;
        y: (parent.height - self.height) / 2;
        border-radius: 2px;
        background: Palette.widget-background;
    }


    handle := Rectangle {
        width: self.height;
        height: parent.height;
        border-radius: self.height / 2;
        border-color: touch.has-hover ? Palette.widget-stroke.darker(100%) :  Palette.widget-stroke;
        border-width: touch.pressed ? 4px : touch.has-hover ? 3px : 2px;
        background: touch.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
        x: (root.width - handle.width) * max(0, min(1, (root.value - root.minimum)/(root.maximum - root.minimum)));
    }
    touch := TouchArea {
        width: parent.width;
        height: parent.height;
        property <float> pressed-value;
        pointer-event(event) => {
            if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
                self.pressed-value = root.value;
            }
        }
        moved => {
            if (self.enabled && self.pressed) {
                root.value = max(root.minimum, min(root.maximum,
                    self.pressed-value + (touch.mouse-x - touch.pressed-x) * (root.maximum - root.minimum) / (root.width - handle.width)));
                root.changed(root.value);
            }
        }
    }
}

component Hyperlink inherits Text {
    color: Palette.hyper-blue;
    TouchArea { mouse-cursor: pointer; }
    in-out property<string> link;
}

component DragValue inherits TouchArea {
    in-out property <float> value;
    min-height: t.min-height;
    min-width: Math.max(t.min-width + 10px, 50px);
    Rectangle {
        border-width: 1.5px;
        border-color: root.has-hover ? Palette.widget-stroke : transparent;
        border-radius: 3px;
        background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
        t := Label {
            y:0;
            width: 100%;
            horizontal-alignment: center;
            text: round(root.value);
        }
    }
    moved => {
        if (root.pressed) {
            root.value = root._pressed-value +(root.mouse-x - root.pressed-x) / 2px;
        }
    }
    pointer-event(e) => {
        if (e.kind == PointerEventKind.down) {
            root._pressed-value = root.value;
        }
    }

    in-out property <float> _pressed-value;
    mouse-cursor: MouseCursor.ew-resize;
}

component ProgressBar inherits Rectangle {
    in-out property <float> value;
    min-height: 24px;
    min-width: 100px;
    background: StyleMetrics.textedit-background;
    border-radius: root.height / 2;

    Rectangle {
        x:0;
        height: 100%;
        width: self.height + (parent.width - self.height) * max(0, min(1, root.value / 100));
        border-radius: self.height / 2;
        background: Palette.hyper-blue;
    }
    Label {
        height: 100%;
        vertical-alignment: center;
        x: self.height/2;
        text: round(root.value) + "%";
    }
}


//------ Demo apps -------

component Gallery inherits GridBox {

    function unsel() { r1.checked = false; r2.checked = false; r3.checked = false; }

    Row {
        Text { text: "Label:"; }
        Label { text: "Welcome to the widget gallery!"; }
    }
    Row {
        Text { text: "Hyperlink:"; }
        Hyperlink { text: "Slint homepage"; link: "https://slint-ui.com"; }
    }
    Row {
        Text { text: "TextEdit:"; }
        LineEdit { placeholder-text: "WriteSomething here";}
    }
    Row {
        Text { text: "Button:"; }
        HorizontalLayout {
            alignment: start;
            Button { text: "Click me!"; clicked => { cb.checked = !cb.checked; } }
        }
    }
    Row {
        Text { text: "Checkbox:"; }
        cb := CheckBox { text: "Checkbox"; }
    }
    Row {
        Text { text: "RadioButton:"; }
        HorizontalBox {
            alignment: start;
            r1 := RadioButton { text: "First"; clicked => { root.unsel(); r1.checked = true; } }
            r2 := RadioButton { text: "Second"; clicked => { root.unsel(); r2.checked = true; } }
            r3 := RadioButton { text: "Third"; clicked => { root.unsel(); r3.checked = true; } }
        }
    }
    Row {
        Text { text: "SelectableLabel:"; }
        HorizontalBox {
            alignment: start;
            SelectableLabel { text: "First"; checked <=> r1.checked; clicked => { root.unsel(); r1.checked = true; } }
            SelectableLabel { text: "Second"; checked <=> r2.checked; clicked => { root.unsel(); r2.checked = true; } }
            SelectableLabel { text: "Third"; checked <=> r3.checked; clicked => { root.unsel(); r3.checked = true; } }
        }
    }
    Row {
        Text { text: "ComboBox:"; }
        HorizontalBox {
            alignment: start;
            ComboBox {
                model: ["First", "Second", "Third"];
                selected => {
                    r1.checked = self.current-index == 0;
                    r2.checked = self.current-index == 1;
                    r3.checked = self.current-index == 2;
                }
            }
            Label { text: "Take your pick"; }
        }
    }
    Row {
        Text { text: "Slider:"; }
        sl := Slider { }
    }
    Row {
        Text { text: "DragValue:"; }
        HorizontalLayout {
            alignment: start;
            DragValue { value <=> sl.value; }
        }
    }
    Row {
        Text { text: "ProgressBar:"; }
        ProgressBar { value <=> sl.value; }
    }
    Rectangle {}
}

component TextEditDemo inherits VerticalLayout {
    preferred-height: 150px;
    preferred-width: 300px;
    TextEdit {
        text: "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum";
    }
}

export component Demo inherits Window {
    preferred-width: 1024px;
    preferred-height: 800px;
    background: white;

    w1 := MdiWindow {
        x:0;y:0;
        title: "🗄 Widget Gallery";
        window-x: 30px;
        window-y: 20px;
        Gallery {  }
    }
    w2 := MdiWindow {
        x:0;y:0;
        visible: false;
        title: "🗉 TextEdit";
        window-x: 230px;
        window-y: 520px;
        TextEditDemo {  }
    }

    side-panel := Rectangle {
        border-color: resize-side-panel.has-hover ? Palette.window-border.darker(100%) :  Palette.window-border;
        border-width: 2px;
        background: Palette.window-background;
        x: parent.width - self.width;
        width: side-panel-l.preferred-width;
        height: 100%;

        side-panel-l := VerticalBox {
            alignment: start;
            Label {
                font-weight: 500;
                text: "Slint Demos";
                horizontal-alignment: center;
            }
            Rectangle { height: 2px; background: Palette.window-border; }
            Label {
                preferred-width: 0px;
                text: "This is a demo which is based on the demo from the egui framework";
                wrap: word-wrap;
                horizontal-alignment: center;
            }
            Rectangle { height: 2px; background: Palette.window-border; }
            CheckBox { text: w1.title; checked <=> w1.visible; }
            CheckBox { text: w2.title; checked <=> w2.visible; }

        }
        resize-side-panel := TouchArea {
            x:0;
            height: 100%;
            width: 4px;
            mouse-cursor: ew-resize;
            moved => {
                if (self.pressed) {
                    side-panel.width = max(side-panel-l.min-width, min(root.width, side-panel.width - (self.mouse-x - self.pressed-x)));
                }
            }
        }

    }
}
